﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;

namespace TrainingDemo.Util.NativeUtil
{
    class NativeUtils
    {

        #region Import part

        private delegate bool EnumDelegate(IntPtr hWnd, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool EnumWindows(EnumDelegate enumProc, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate enumProc, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll", EntryPoint = "GetWindowText", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        #endregion


        #region Private Property

        private static NativeUtils m_instance = null;
        IntPtr g_hwndParent = IntPtr.Zero;
        static List<IntPtr> g_lstChidrens = null;

        #endregion

#region Constructor/Destructor/Init

        private NativeUtils() { }

        public static NativeUtils getInstance()
        {
            if (m_instance == null)
            {
                m_instance = new NativeUtils();
            }
            return m_instance;
        }

#endregion




        #region Private Methods

        static EnumDelegate getDesktopWindow = delegate(IntPtr hWnd, IntPtr lParam)
        {
            //bool isRecursive = lParam & Const.GET_WINDOWS_RECURSIVE_FLAG;
            //bool ignoreInvisibleWnd = lParam & Const.IGNORE_INVISIBLE_WINDOWS_FLAG;
            //bool ignoreSystemWnd = lParam & Const.IGNORE_SYSTEM_WINDOWS_FLAG;

            //if (ignoreSystemWnd)
            //{
            int nRet;
            // Pre-allocate 256 characters, since this is the maximum class name length.
            StringBuilder ClassName = new StringBuilder(256);
            //Get the window class name
            nRet = GetClassName(hWnd, ClassName, ClassName.Capacity);
            if (nRet != 0)
            {
                if ((string.Compare(ClassName.ToString(), "shell_traywnd", true, CultureInfo.InvariantCulture) == 0)
                    || (string.Compare(ClassName.ToString(), "progman", true, CultureInfo.InvariantCulture) == 0)
                    || (string.Compare(ClassName.ToString(), "System Explorer", true, CultureInfo.InvariantCulture) == 0)
                    )
                {
                    return true;
                }
            }

            string strTitle = GetWindowTitle(hWnd, 255);
            if (IsWindowVisible(hWnd) && string.IsNullOrEmpty(strTitle) == false)
            {
                if ( !(string.Compare(strTitle.ToString(), "System Explorer", true, CultureInfo.InvariantCulture) == 0) )
                {
                    g_lstChidrens.Add(hWnd);
                }
            }
            return true;
        };


        #endregion


        #region Public Methods

        /// <summary>
        /// get list of window on desktop
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="children"></param>
        /// <param name="ignoreInvisibleWnd"></param>
        /// <returns></returns>
        public static int getListDesktopWindows(IntPtr parent, ref List<IntPtr> children, bool ignoreInvisibleWnd)
        {
            if (children == null)
                return -1;
            else
            {
                children.Clear();
            }

            IntPtr lParam = IntPtr.Zero;
            g_lstChidrens = new List<IntPtr>();
            if (EnumDesktopWindows(IntPtr.Zero, getDesktopWindow, IntPtr.Zero))
            {
                children = g_lstChidrens;
            }
            return 0;
        }

        public static string GetWindowTitle(IntPtr pHandle, int nLen)
        {
            StringBuilder strbTitle = new StringBuilder(nLen);
            int nLength = GetWindowText(pHandle, strbTitle, strbTitle.Capacity + 1);
            return strbTitle.ToString();
        }


        #endregion

    }
}
